import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Date;
import java.rmi.server.UID;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;


public class SerializeText {

    /**Nom physique des fichiers*/
    private static final String FILE_TRANSPORT = "Transports.txt";
    private static final String FILE_TRAJET = "Trajets.txt";
    private static final String FILE_RESERVATION = "Reservations.txt";



    static void saveServeur(Serveur s) {
        try {
            SerializeText.saveTransports(s.getTransports());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    static void saveTransports(List<Transport> transports) throws IOException {
        Writer wTransport          = new FileWriter(FILE_TRANSPORT);
        Writer wTrajet          = new FileWriter(FILE_TRAJET);
        Writer wResa          = new FileWriter(FILE_RESERVATION);

        //Sauvegarder les transports
        //
        for(Transport t : transports)
        {
            //idTransport++;
            //Obtenir les attributs en String
            //
            String typeTransport = t.getType().name();
            String capacity = Integer.toString(t.getCapacity());  
            String idTransport = Integer.toString(t.getIdTransport());
            String uneLigne = typeTransport + ";" + capacity + ";" + idTransport + "\n";

            //Ecrire la ligne dans le fichier texte transport
            //
            wTransport.write(uneLigne);

            //Sauvegarder les trajets
            //            
            for(Trajet tra : t.getJourney()) {
                //idTrajet++;
                //Obtenir les attributs en String
                //
                String start = tra.getStart().name();
                String arrived = tra.getArrived().name();
                String startDate = getFormatedDate(tra.getStartDate());
                String arrivedDate = getFormatedDate(tra.getArrivedDate());
                //String freeCapacity = Integer.toString(tra.getFreeCapacity());
                String idTrajet = Integer.toString(tra.getIdTrajet());

                //Ecrire la ligne dans le fichier texte trajet
                //
                uneLigne = start + ";" + arrived + ";" + startDate + ";" + arrivedDate + ";" + idTransport + ";" + idTrajet + "\n";
                wTrajet.write(uneLigne);

                //Sauvegarder les voyageur
                //
                for(Voyageur v : tra.getReservations()) {
                    uneLigne = v.getPrenom() + ";" + v.getNom() + ";" + idTrajet + "\n";
                    wResa.write(uneLigne);
                }
            }
        }
        wTransport.close();
        wTrajet.close();
        wResa.close();
    }

    static Serveur loadServeur() {


        Serveur s = new Serveur();
        try {
            List<Transport> transports = loadTransport();
            for(Transport t : transports) {
                s.addTransport(t);
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }     
        return s;

    }
    
    static public List<Transport> loadTransport() throws Exception {
        String ligne;
        Reader rTransport          =   new FileReader(FILE_TRANSPORT);
        Reader rTrajet          =   new FileReader(FILE_TRAJET);
        Reader rResa          =   new FileReader(FILE_RESERVATION);
        BufferedReader br =   new BufferedReader(rTransport);
        HashMap<Integer, Transport > transports = new HashMap<Integer, Transport>();
        HashMap<Integer, List<Voyageur> > reservations = new  HashMap<Integer, List<Voyageur> >();
        
        int idTransport=0;
        int idTrajet=0;
        
        Transport t;
        //Récuperer les transports
        //
        while ( (ligne = br.readLine()) != null)
        {
            t = createTransport(ligne);
            transports.put(t.getIdTransport(),createTransport(ligne));
        }
        rTransport.close();

        //Recuperer les reservations
        //
        br =   new BufferedReader(rResa);

        while ( (ligne = br.readLine()) != null)
        {
            //Creer la reservation
            //
            Voyageur resa = createReservation(ligne);

            //Obtenir l'id Trajet (qui est le numéro de ligne du trajet dans le fichier texte)
            //
           idTrajet = getIdTrajetOfReservation(ligne);

            //Verifier que l'index n'est pas null
            //           
            if(reservations.get(idTrajet) == null) {
                reservations.put(idTrajet, new ArrayList<Voyageur>());
            }

            //Ajouter la reservation dans le dictionnaire avec l'id du Trajet
            //    
            try {
                reservations.get(idTrajet).add(resa);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        //Recuperer les Trajets
        //
        br =   new BufferedReader(rTrajet);

        //Le compteur ligne est l'index d'un trajet (un trajet etant unique)
        //
        //idTrajet=0;
        while ( (ligne = br.readLine()) != null)
        {
            
            //Creer le trajet
            //
            Trajet tr = createTrajet(ligne);
            
            //Obtenir l'id Transport
            //
            idTransport = getIdTransportOfTrajet(ligne);



            //Ajouter le trajet au transport correspondant
            //                
            if(transports.get(idTransport) != null) {
                transports.get(idTransport).addJourney(tr);
            }  

            //Verifier le trajet comporte des réservations
            //
            if(reservations.get(tr.getIdTrajet()) != null) {
                for(Voyageur v : reservations.get(tr.getIdTrajet())) {
                    tr.addReservation(v);
                }
            }                     
        }
        
        ArrayList<Transport> result = new ArrayList<Transport>();
        
        for(Transport trans : transports.values()) {
            result.add(trans);
        }
        
        return result;
    }

    static private Voyageur createReservation(String ligne) {
        StringTokenizer st = new StringTokenizer(ligne, ";");
        return new Voyageur(st.nextToken(), st.nextToken());
    }

    static private int getIdTrajetOfReservation(String ligne) {
        StringTokenizer st = new StringTokenizer(ligne, ";");
        String res = new String();
        for(int i=0; i<3 ; i++) {
            res=st.nextToken();
        }

        return Integer.parseInt(res);
    }

    /**
     * Creer un transport a partir d'une String formaté.
     * @param ligne
     * @throws NoSuchElementException
     */
    static Transport createTransport(String ligne) throws NoSuchElementException
    {
        StringTokenizer st = new StringTokenizer(ligne, ";");
        String typeTransport = st.nextToken();
        int capacity = Integer.parseInt(st.nextToken());
        int idTransport = Integer.parseInt(st.nextToken());
        Transport res = new Transport(TypeTransport.valueOf(typeTransport), capacity, idTransport);
        return res;
    }

    /**
     * Creer un transport a partir d'une String formaté.
     * @param ligne
     * @throws Exception 
     */
    static Trajet createTrajet(String ligne) throws Exception
    {
        StringTokenizer st = new StringTokenizer(ligne, ";");
        Ville start = Ville.valueOf(st.nextToken());
        Ville arrived = Ville.valueOf(st.nextToken());
        Date startDate = stringToDate(st.nextToken());
        Date arrivedDate = stringToDate(st.nextToken());
        int idTransport = Integer.parseInt(st.nextToken());
        int idTrajet = Integer.parseInt(st.nextToken());
        Trajet res = new Trajet(start, arrived, startDate, arrivedDate, idTrajet);
        return res;
    }

    /**
     * Obtnir l'id du Transport correspondant a la ligne
     */
    static private int getIdTransportOfTrajet(String ligne) {
        StringTokenizer st = new StringTokenizer(ligne, ";");
        String res = new String();
        for(int i=0; i<5 ; i++) {
            res=st.nextToken();
        }

        return Integer.parseInt(res);
    }

    public static Date stringToDate(String sDate) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy-HH:mm");
        return (Date) sdf.parse(sDate);
    }

    public static String getFormatedDate(Date date) {

        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy-HH:mm");
        return dateFormat.format(date);
    }
}
